
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Unit Testing - vue.js</title>
        <meta charset="utf-8">
        <meta name="description" content="Vue.js - Intuitive, Fast and Composable MVVM for building interactive interfaces.">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
        <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,600|Roboto Mono' rel='stylesheet' type='text/css'>
        <link href='//fonts.googleapis.com/css?family=Dosis:300,500&text=Vue.js' rel='stylesheet' type='text/css'>
        <link href="//cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css" rel='stylesheet' type='text/css'>
        <link rel="icon" href="/images/logo.png" type="image/x-icon">
        <script>
            window.PAGE_TYPE = "guide"
        </script>
        <link rel="stylesheet" href="/css/page.css">
        <script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-46852172-1', 'vuejs.org');
  ga('send', 'pageview');
</script>
        <script src="/js/vue.js"></script>
    </head>
    <body>
        <div id="mobile-bar">
            <a class="menu-button"></a>
            <a class="logo" href="/"></a>
        </div>
        
            <div id="header">
  <a id="logo" href="/">
    <img src="/images/logo.png">
    <span>Vue.js <sup>2.0 RC</sup></span>
  </a>
  <span style="
    position: absolute;
    top: 100%;
    left: 60px;
    padding: 0 10px;
    background: #ef9f00;
    border-radius: 3px;
    margin-top: -15px;
    line-height: 30px;
    color: white;
    font-weight: bold;
    letter-spacing: 1px;
    box-shadow: 0 1px 2px rgba(0,0,0,.3);
  ">
    WORK IN PROGRESS
  </span>
  <ul id="nav">
    <li>
  <form id="search-form">
    <input type="text" id="search-query-nav" class="search-query st-default-search-input">
  </form>
</li>
<li><a href="/guide/" class="nav-link current">Guide</a></li>
<li><a href="/api/" class="nav-link">API</a></li>
<li><a href="/examples/" class="nav-link">Examples</a></li>
<li><a href="/blog/" class="nav-link">Blog</a></li>
<li class="nav-dropdown-container">
  <a class="nav-link">Community</a><span class="arrow"></span>
  <ul class="nav-dropdown">
    <li><a href="https://github.com/vuejs/vue" class="nav-link" target="_blank">GitHub</a></li>
    <li><a href="http://forum.vuejs.org" class="nav-link" target="_blank">Forum</a></li>
    <li><a href="https://gitter.im/vuejs/vue" class="nav-link" target="_blank">Chat</a></li>
    <li><a href="https://twitter.com/vuejs" class="nav-link" target="_blank">Twitter</a></li>
  </ul>
</li>


  </ul>
</div>

            <div id="main">
                
                    
    <div class="sidebar">
    <ul class="main-menu">
        <li>
  <form id="search-form">
    <input type="text" id="search-query-sidebar" class="search-query st-default-search-input">
  </form>
</li>
<li><a href="/guide/" class="nav-link current">Guide</a></li>
<li><a href="/api/" class="nav-link">API</a></li>
<li><a href="/examples/" class="nav-link">Examples</a></li>
<li><a href="/blog/" class="nav-link">Blog</a></li>
<li class="nav-dropdown-container">
  <a class="nav-link">Community</a><span class="arrow"></span>
  <ul class="nav-dropdown">
    <li><a href="https://github.com/vuejs/vue" class="nav-link" target="_blank">GitHub</a></li>
    <li><a href="http://forum.vuejs.org" class="nav-link" target="_blank">Forum</a></li>
    <li><a href="https://gitter.im/vuejs/vue" class="nav-link" target="_blank">Chat</a></li>
    <li><a href="https://twitter.com/vuejs" class="nav-link" target="_blank">Twitter</a></li>
  </ul>
</li>


    </ul>
    <div class="list">
        <div id="donate" style="margin-bottom: 20px">
            <span class="wrapper" style="width: 110px">
              <img src="/images/patreon.png">
              <a href="/support-vuejs">Support Vue.js</a>
            </span>
        </div>
        <h2>
            Guide
            <select class="version-select">
                <option value="rc" selected>2.0</option>
                <!-- !!TODO: Update value to subdomain when 2.0 is released -->
                <option value="">1.0</option>
                <option>0.12</option>
                <option>0.11</option>
            </select>
        </h2>
        <ul class="menu-root">
            
                
                
                  <li><h3>Essentials</h3></li>
                
                
                
                <li>
                    <a href="/guide/installation.html" class="sidebar-link">Installation</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/index.html" class="sidebar-link">Introduction</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/instance.html" class="sidebar-link">The Vue Instance</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/syntax.html" class="sidebar-link">Template Syntax</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/computed.html" class="sidebar-link">Computed Properties and Watchers</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/class-and-style.html" class="sidebar-link">Class and Style Bindings</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/conditional.html" class="sidebar-link">Conditional Rendering</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/list.html" class="sidebar-link">List Rendering</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/events.html" class="sidebar-link">Event Handling</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/forms.html" class="sidebar-link">Form Input Bindings</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/components.html" class="sidebar-link">Components</a>
                </li>
            
                
                
                
                  <li><h3>Advanced</h3></li>
                
                
                <li>
                    <a href="/guide/transitions.html" class="sidebar-link">Transitions: Entering, Leaving, and Lists</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/transitioning-state.html" class="sidebar-link">Transitioning State</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/render-function.html" class="sidebar-link">Render Functions</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/reactivity.html" class="sidebar-link">Reactivity in Depth</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/custom-directive.html" class="sidebar-link">Custom Directives</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/mixins.html" class="sidebar-link">Mixins</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/plugins.html" class="sidebar-link">Plugins</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/single-file-components.html" class="sidebar-link">Single File Components</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/routing.html" class="sidebar-link">Routing</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/state-management.html" class="sidebar-link">State Management</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/unit-testing.html" class="sidebar-link current">Unit Testing</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/ssr.html" class="sidebar-link">Server-Side Rendering</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/migration.html" class="sidebar-link">Migration from 1.x</a>
                </li>
            
                
                
                
                
                  <li><h3>Meta</h3></li>
                
                <li>
                    <a href="/guide/comparison.html" class="sidebar-link">Comparison with Other Frameworks</a>
                </li>
            
                
                
                
                
                <li>
                    <a href="/guide/join.html" class="sidebar-link">Join the Vue.js Community!</a>
                </li>
            
        </ul>
    </div>
</div>


<div class="content guide with-sidebar unit-testing-guide">
    <div id="ad">
  <script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?zoneid=1673&serve=C6AILKT&placement=vuejs" id="_carbonads_js"></script>
</div>

    <h1>Unit Testing</h1>
    <h2 id="Setup-and-Tooling"><a href="#Setup-and-Tooling" class="headerlink" title="Setup and Tooling"></a>Setup and Tooling</h2><p>Anything compatible with a module-based build system will work, but if you’re looking for a specific recommendation, try the <a href="http://karma-runner.github.io/0.12/index.html" target="_blank" rel="external">Karma</a> test runner. It has a lot of community plugins, including support for <a href="https://github.com/webpack/karma-webpack" target="_blank" rel="external">Webpack</a> and <a href="https://github.com/Nikku/karma-browserify" target="_blank" rel="external">Browserify</a>. For detailed setup, please refer to each project’s respective documentation, though these example Karma configurations for <a href="https://github.com/vuejs/vue-loader-example/blob/master/build/karma.conf.js" target="_blank" rel="external">Webpack</a> and <a href="https://github.com/vuejs/vueify-example/blob/master/karma.conf.js" target="_blank" rel="external">Browserify</a> may help you get started.</p>
<h2 id="Simple-Assertions"><a href="#Simple-Assertions" class="headerlink" title="Simple Assertions"></a>Simple Assertions</h2><p>In terms of code structure for testing, you don’t have to do anything special in your components to make them testable. Just export the raw options:</p>
<figure class="highlight html"><table><tr><td class="code"><pre><div class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></div><div class="line">  <span class="tag">&lt;<span class="name">span</span>&gt;</span>&#123;&#123; message &#125;&#125;<span class="tag">&lt;/<span class="name">span</span>&gt;</span></div><div class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></div><div class="line"></div><div class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></div><div class="line">  <span class="keyword">export</span> <span class="keyword">default</span> &#123;</div><div class="line">    data () &#123;</div><div class="line">      <span class="keyword">return</span> &#123;</div><div class="line">        message: <span class="string">'hello!'</span></div><div class="line">      &#125;</div><div class="line">    &#125;,</div><div class="line">    created () &#123;</div><div class="line">      <span class="keyword">this</span>.message = <span class="string">'bye!'</span></div><div class="line">    &#125;</div><div class="line">  &#125;</div><div class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></div></pre></td></tr></table></figure>
<p>When you test that component, all you have to do is import the object along with Vue to make many common assertions:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><div class="line"><span class="comment">// Import Vue and the component being tested</span></div><div class="line"><span class="keyword">import</span> Vue <span class="keyword">from</span> <span class="string">'vue'</span></div><div class="line"><span class="keyword">import</span> MyComponent <span class="keyword">from</span> <span class="string">'path/to/MyComponent.vue'</span></div><div class="line"></div><div class="line"><span class="comment">// Here are some Jasmine 2.0 tests, though you can</span></div><div class="line"><span class="comment">// use any test runner / assertion library combo you prefer</span></div><div class="line">describe(<span class="string">'MyComponent'</span>, () =&gt; &#123;</div><div class="line">  <span class="comment">// Inspect the raw component options</span></div><div class="line">  it(<span class="string">'has a created hook'</span>, () =&gt; &#123;</div><div class="line">    expect(<span class="keyword">typeof</span> MyComponent.created).toBe(<span class="string">'function'</span>)</div><div class="line">  &#125;)</div><div class="line"></div><div class="line">  <span class="comment">// Evaluate the results of functions in</span></div><div class="line">  <span class="comment">// the raw component options</span></div><div class="line">  it(<span class="string">'sets the correct default data'</span>, () =&gt; &#123;</div><div class="line">    expect(<span class="keyword">typeof</span> MyComponent.data).toBe(<span class="string">'function'</span>)</div><div class="line">    <span class="keyword">const</span> defaultData = MyComponent.data()</div><div class="line">    expect(defaultData.message).toBe(<span class="string">'hello!'</span>)</div><div class="line">  &#125;)</div><div class="line"></div><div class="line">  <span class="comment">// Inspect the component instance on mount</span></div><div class="line">  it(<span class="string">'correctly sets the message when created'</span>, () =&gt; &#123;</div><div class="line">    <span class="keyword">const</span> vm = <span class="keyword">new</span> Vue(MyComponent).$mount()</div><div class="line">    expect(vm.message).toBe(<span class="string">'bye!'</span>)</div><div class="line">  &#125;)</div><div class="line"></div><div class="line">  <span class="comment">// Mount an instance and inspect the render output</span></div><div class="line">  it(<span class="string">'renders the correct message'</span>, () =&gt; &#123;</div><div class="line">    <span class="keyword">const</span> Ctor = Vue.extend(MyComponent)</div><div class="line">    <span class="keyword">const</span> vm = <span class="keyword">new</span> Ctor().$mount()</div><div class="line">    expect(vm.$el.textContent).toBe(<span class="string">'bye!'</span>)</div><div class="line">  &#125;)</div><div class="line">&#125;)</div></pre></td></tr></table></figure>
<h2 id="Writing-Testable-Components"><a href="#Writing-Testable-Components" class="headerlink" title="Writing Testable Components"></a>Writing Testable Components</h2><p>A lot of components’ render output are primarily determined by the props they receive. In fact, if a component’s render output solely depends on its props, it becomes quite straightforward to test, similar to asserting the return value of a pure function with different arguments. Take an contrived example:</p>
<figure class="highlight html"><table><tr><td class="code"><pre><div class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></div><div class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123; msg &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></div><div class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></div><div class="line"></div><div class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></div><div class="line">  <span class="keyword">export</span> <span class="keyword">default</span> &#123;</div><div class="line">    props: [<span class="string">'msg'</span>]</div><div class="line">  &#125;</div><div class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></div></pre></td></tr></table></figure>
<p>You can assert its render output with different props using the <code>propsData</code> option:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><div class="line"><span class="keyword">import</span> Vue <span class="keyword">from</span> <span class="string">'vue'</span></div><div class="line"><span class="keyword">import</span> MyComponent <span class="keyword">from</span> <span class="string">'./MyComponent.vue'</span></div><div class="line"></div><div class="line"><span class="comment">// helper function that mounts and returns the rendered text</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">getRenderedText</span> (<span class="params">Component, propsData</span>) </span>&#123;</div><div class="line">  <span class="keyword">const</span> Ctor = Vue.extend(MyComponent)</div><div class="line">  <span class="keyword">const</span> vm = <span class="keyword">new</span> Ctor(&#123; propsData &#125;).$mount()</div><div class="line">  <span class="keyword">return</span> vm.$el.textContent</div><div class="line">&#125;</div><div class="line"></div><div class="line">describe(<span class="string">'MyComponent'</span>, () =&gt; &#123;</div><div class="line">  it(<span class="string">'render correctly with different props'</span>, () =&gt; &#123;</div><div class="line">    expect(getRenderedText(MyComponent, &#123;</div><div class="line">      msg: <span class="string">'Hello'</span></div><div class="line">    &#125;)).toBe(<span class="string">'Hello'</span>)</div><div class="line"></div><div class="line">    expect(getRenderedText(MyComponent, &#123;</div><div class="line">      msg: <span class="string">'Bye'</span></div><div class="line">    &#125;)).toBe(<span class="string">'Bye'</span>)</div><div class="line">  &#125;)</div><div class="line">&#125;)</div></pre></td></tr></table></figure>
<h2 id="Asserting-Asynchronous-Updates"><a href="#Asserting-Asynchronous-Updates" class="headerlink" title="Asserting Asynchronous Updates"></a>Asserting Asynchronous Updates</h2><p>Since Vue <a href="/guide/reactivity.html#Async-Update-Queue">performs DOM updates asynchronously</a>, assertions on DOM updates resulting from state change will have to be made in a <code>Vue.nextTick</code> callback:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><div class="line"><span class="comment">// Inspect the generated HTML after a state update</span></div><div class="line">it(<span class="string">'updates the rendered message when vm.message updates'</span>, done =&gt; &#123;</div><div class="line">  <span class="keyword">const</span> vm = <span class="keyword">new</span> Vue(MyComponent).$mount()</div><div class="line">  vm.message = <span class="string">'foo'</span></div><div class="line"></div><div class="line">  <span class="comment">// wait a "tick" after state change before asserting DOM updates</span></div><div class="line">  Vue.nextTick(() =&gt; &#123;</div><div class="line">    expect(vm.$el.textContent).toBe(<span class="string">'foo'</span>)</div><div class="line">    done()</div><div class="line">  &#125;)</div><div class="line">&#125;)</div></pre></td></tr></table></figure>
<p>We are planning to work on a collection of common test helpers that makes it even simpler to render components with different constraints (e.g. shallow rendering that ignores child components) and assert their output.</p>

    
      <div class="guide-links">
        
          <span>← <a href="/guide/state-management.html">State Management</a></span>
        
        
          <span style="float:right"><a href="/guide/ssr.html">Server-Side Rendering</a> →</span>
        
      </div>
    
    <div class="footer">
      Caught a mistake or want to contribute to the documentation?
      <a href="https://github.com/vuejs/vuejs.org/blob/master/src/guide/unit-testing.md" target="_blank">
        Edit this page on Github!
      </a>
    </div>
</div>

                
            </div>
            <script src="//cdn.jsdelivr.net/docsearch.js/1/docsearch.min.js"></script>
            <script src="/js/smooth-scroll.min.js"></script>
            <script src="/js/common.js"></script>
        

        <script src="//cdnjs.cloudflare.com/ajax/libs/fastclick/1.0.6/fastclick.min.js"></script><script src="https://cdn.jsdelivr.net/gh/shentao/vuejs-outdated-docs-modal@v1.3/prompt.min.js"></script>
        <script>
            document.addEventListener('DOMContentLoaded', function() {
                FastClick.attach(document.body);
            }, false);
        </script>
    </body>
</html>
